﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ListIt.DAL
{
    public class ListItDAL : IDisposable, IListItDAL
    {
        #region Private Variables

        protected ListItEntities _Entities;

        #endregion

        #region Construction & Destructor

        public ListItDAL()
        {
            _Entities = new ListItEntities();
        }

        public void Dispose()
        {
            _Entities.Connection.Close();
            _Entities.Dispose();
        }
        #endregion

        #region IListItDAL Members

        public void ClearJobBackLog()
        {
            var records = from backlog in _Entities.JobBackLogs
                          select backlog;

            foreach (var record in records)
                _Entities.JobBackLogs.DeleteObject(record);

            _Entities.SaveChanges();
        }

        public JobBackLog AddJobToBackLog(string deviceID, string customerName, string pickupAddress, string specialInstructionstring,
            string destinationAddress, DateTime travelDate, string mobileNo, string telNo, short vehicleType,
            int taxiCoy, double pickupLong, double pickupLat)
        {
            JobBackLog job = new JobBackLog();
            job.DeviceID = deviceID;
            job.CustomerName = customerName;
            job.PickupAddress = pickupAddress;
            job.SpecialInstruction = specialInstructionstring;
            job.DestinationAddress = destinationAddress;
            job.TravelDate = travelDate;
            job.MobileNo = mobileNo;
            job.TelNo = telNo;
            job.TaxiCoy = taxiCoy;
            job.PendingDriver = false;
            job.VehicleType = vehicleType;
            job.PickupLongituted = Convert.ToDecimal(pickupLong);
            job.PickupLatitude = Convert.ToDecimal(pickupLat);

            _Entities.JobBackLogs.AddObject(job);
            _Entities.SaveChanges();

            return job;
        }

        public ActiveJob AddJobToActive(JobBackLog jobBacklog, string taxiLicenseNo)
        {
            ActiveJob job = new ActiveJob();
            job.DeviceID = jobBacklog.DeviceID;
            job.CustomerName = jobBacklog.CustomerName;
            job.PickupAddress = jobBacklog.PickupAddress;
            job.SpecialInstruction = jobBacklog.SpecialInstruction;
            job.DestinationAddress = jobBacklog.DestinationAddress;
            job.LicenseNo = taxiLicenseNo.Trim();
            job.MobileNo = jobBacklog.MobileNo;
            job.TelNo = jobBacklog.TelNo;
            job.TimeRequested = DateTime.Now;
            job.DeclinedDrivers = jobBacklog.DeclinedDrivers;
            job.VehicleType = jobBacklog.VehicleType;
            job.PickupLatitude = jobBacklog.PickupLatitude;
            job.PickupLongituted = jobBacklog.PickupLongituted;

            _Entities.ActiveJobs.AddObject(job);
            _Entities.SaveChanges();

            return job;
        }

        public JobHistory AddJobToHistory(ActiveJob activeJob)
        {
            JobHistory job = new JobHistory();
            job.DeviceID = activeJob.DeviceID;
            job.LicenseNo = activeJob.LicenseNo.Trim();
            job.CustomerName = activeJob.CustomerName;
            job.PickupAddress = activeJob.PickupAddress;
            job.SpecialInstruction = activeJob.SpecialInstruction;
            job.DestinationAddress = activeJob.DestinationAddress;
            job.TimeRequested = activeJob.TimeRequested;
            job.TimeCompleted = DateTime.Now;
            job.MobileNo = activeJob.MobileNo;
            job.TelNo = activeJob.TelNo;
            job.VehicleType = activeJob.VehicleType;

            _Entities.JobHistories.AddObject(job);
            _Entities.SaveChanges();

            return job;
        }

        public string GetSerializedJob(ActiveJob job)
        {
            JobSerializedClass jsc = new JobSerializedClass(job);

            System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(jsc.GetType());
            MemoryStream ms = new MemoryStream();
            serializer.WriteObject(ms, jsc);
            return Encoding.Default.GetString(ms.ToArray());
        }

        public void MoveJobToActive()
        {
            throw new NotImplementedException();
        }

        public void MoveJobToComplete()
        {
            throw new NotImplementedException();
        }

        public ListItEntities ListItEntities
        {
            get
            {
                return _Entities;
            }
        }

        public bool Authenticate(string username, string password)
        {
            var users = from Users in _Entities.Securities
                        where Users.UserName == username
                        select Users;

            List<Security> userList = users.ToList();

            foreach (Security user in userList)
            {
                if (user.Password == password)
                    return true;
            }

            return false;
        }

        public int AuthenticateTaxi(string deviceID, string username, string password, out string message)
        {
            var taxis = _Entities.Taxis.SingleOrDefault(t => t.DeviceID == deviceID);
            WEBSERVER_MESSAGES result = 0; 
            message = "";

            if (taxis == null)
            {
                message = "Device is not registered. Please contact list-it.";
                result = WEBSERVER_MESSAGES.UNREGISTERED_DEVICE;
            }
            else
            {
                if (taxis.Username != username)
                {
                    message = "Username is invalid";
                    result = WEBSERVER_MESSAGES.INVALID_USERNAME;
                }
                else if (taxis.Password != password)
                {
                    message = "Password is invalid";
                    result = WEBSERVER_MESSAGES.INVALID_PASSWORD;
                }
                else
                    result = WEBSERVER_MESSAGES.LOGGED_IN;
            }

            return (int)result;
        }

        public string AddUser(string username, string password, string email, string passPhrase, string answer)
        {
            var users = from Users in _Entities.Securities
                        where Users.UserName == username
                        select Users;

            List<Security> userList = users.ToList();

            // check for user existance
            if (userList.Count != 0)
                return "User already exists";

            // validate password criteria
            if (password == "")
                return "Password string needs to contain letters";

            // validate other fields
            if (passPhrase == "")
                return "You have not provided a Pass Phrase";

            if (answer == "")
                return "You have not provided an answer for you Pass Phrase:  " + passPhrase;

            Security security = new Security();
            security.UserName = username;
            security.Password = password;
            security.Email = email;
            security.PassPhrase = passPhrase;
            security.Answer = answer;

            return ""; // all is OK
        }

        public void RegisterCustomerDevice(string deviceID, string customerName, string mobileNo)
        {
            var customer = ListItEntities.Customers.SingleOrDefault(c => c.DeviceID == deviceID);

            if (customer == null)
            {
                customer = new Customer();
                ListItEntities.AddToCustomers(customer);
                customer.DeviceID = deviceID;
            }

            customer.Owner = customerName;
            customer.PhoneNumber = mobileNo;

            ListItEntities.SaveChanges();
        }
        #endregion

        #region IListItJobMonitor

        #endregion
    }

    public enum WEBSERVER_MESSAGES
    {
        OK = 0,
        INVALID_USERNAME,
        INVALID_PASSWORD,
        UNREGISTERED_DEVICE,
        DEVICE_NOT_LOGGED_IN,
        LOGGED_IN,
        LOGGED_OUT,
        STATUS_BUSY,
        STATUS_AVAILABLE,
        CONNECTION_ERROR,
        UNKNOWN_ERROR,
        SERVER_ERROR,
        JOB_TERMINATE,
        JOB_WITHDRAW,
        JOB_COMPLETE,
        JOB_EXPIRED,
        HAS_JOB
    };
}